#include "Camera.h"

#include <cmath>
#include <iostream>

const float Camera::SENSITIVITY = 1.0f;
const float Camera::DEFAULT_SPEED = 0.1f;

const float X_ROTATION_LIMIT = 80.0f;
const float Y_ROTATION_LIMIT = 360.0f;

Camera::Camera() :
m_pos(vec3(0.0f, 0.0f, 0.0f)),
m_look(vec3(0.0f, 0.0f, 1.0f)),
m_yRot(0.0f),
m_xRot(0.0f),
m_speed(DEFAULT_SPEED),
m_move(false),
m_strafe(false),
m_focalLength(50.0f),
m_focusDistance(2000.0f),
m_focalRatio(2.8f),
m_frameSize(35.0f)
{
}

Camera::Camera(vec3 pos, vec3 look) :
m_pos(pos),
m_look(look),
m_yRot(0.0f),
m_xRot(0.0f),
m_speed(DEFAULT_SPEED),
m_move(false),
m_strafe(false),
m_focalLength(50.0f),
m_focusDistance(2000.0f),
m_focalRatio(2.8f),
m_frameSize(35.0f)
{
}

Camera::~Camera()
{
}

void Camera::turn(vec2 movement)
{
    float xAngle = movement.y * SENSITIVITY;
    float yAngle = movement.x * SENSITIVITY;

    m_xRot += xAngle;
    m_yRot += yAngle;

    if (m_xRot < -X_ROTATION_LIMIT)
    {
        m_xRot = -X_ROTATION_LIMIT;
    }
    else if (m_xRot > X_ROTATION_LIMIT)
    {
        m_xRot = X_ROTATION_LIMIT;
    }

    if (m_yRot < -Y_ROTATION_LIMIT)
    {
        m_yRot += Y_ROTATION_LIMIT;
    }
    else if (m_yRot > Y_ROTATION_LIMIT)
    {
        m_yRot -= Y_ROTATION_LIMIT;
    }

    m_look.x = -sin(m_yRot * DEG_TO_RAD) * cos(m_xRot * DEG_TO_RAD);
    m_look.y = -sin(m_xRot * DEG_TO_RAD);
    m_look.z = cos(m_yRot * DEG_TO_RAD) * cos(m_xRot * DEG_TO_RAD);
}

void Camera::moveForward()
{
    m_pos += m_look * m_speed;
}

void Camera::moveBackwards()
{
    m_pos -= m_look * m_speed;
}

void Camera::strafeLeft()
{
    m_pos.x += cos(m_yRot * DEG_TO_RAD) * m_speed;
	m_pos.z += sin(m_yRot * DEG_TO_RAD) * m_speed;
}

void Camera::strafeRight()
{
    m_pos.x -= cos(m_yRot * DEG_TO_RAD) * m_speed;
	m_pos.z -= sin(m_yRot * DEG_TO_RAD) * m_speed;
}

vec3 Camera::getPos() const
{
    return m_pos;
}

vec3 Camera::getLook() const
{
    return m_look;
}

vec3 Camera::getLookAt() const
{
    return m_pos + m_look;
}

float Camera::getFocalLength() const
{
    return m_focalLength;
}

float Camera::getFocusDistance() const
{
    return m_focusDistance;
}

float Camera::getFocalRatio() const
{
    return m_focalRatio;
}

float Camera::getFrameSize() const
{
    return m_frameSize;
}

void Camera::setPosition(vec3 pos)
{
    m_pos = pos;
}

void Camera::setMovementStatus(bool status)
{
    m_move = status;

    if (m_move && m_strafe)
    {
        setDiagonalSpeed();
    }
    else
    {
        setDefaultSpeed();
    }
}

void Camera::setStrafeStatus(bool status)
{
    m_strafe = status;

    if (m_move && m_strafe)
    {
        setDiagonalSpeed();
    }
    else
    {
        setDefaultSpeed();
    }
}

void Camera::setDiagonalSpeed()
{
    m_speed = DEFAULT_SPEED * COS45;
}

void Camera::setDefaultSpeed()
{
    m_speed = DEFAULT_SPEED;
}

void Camera::setFocalLength(float focalLength)
{
    m_focalLength = focalLength;
}

void Camera::setFocusDistance(float focusDistance)
{
    m_focusDistance = focusDistance;
}

void Camera::setFocalRatio(float focalRatio)
{
    m_focalRatio = focalRatio;
}

void Camera::setFrameSize(float frameSize)
{
    m_frameSize = frameSize;
}